{
CSVStringInfo v1.1
(Created in Delphi 2.0)
By: Craig Manley
    Churchillweg 224
    1314 TG  Almere
    Netherlands
    Tel.: Int'l access code +31 36 5300347
    E-mail: c.manley@tip.nl
    Homepages: http://www1.tip.nl/~t960341 http://www.skybound.club.tip.nl

Description:
CSVStringInfo is a Delphi component that is used to break up comma delimited 
strings into separate fields similar to the way dBase does.
There is a CommaText function in Delphi, but it doesn't work the same way.
TCSVStringInfo works both during design time and run-time.

Changes:
Version 1.1
Changed the field extracting algorithm. In version 1.0 it worked exactly the
same way as in Microsoft Visual FoxPro. But seeing that the way Microsoft's
product does it is buggy (as usual), I changed the algorithm. 
	Example:
	The string 1234,"Johny "B" Goode","music" would be separated by FoxPro
	into:	1234
		Johny
		B
		 Goode
		music
	Borland dBase will return these fields (slightly better):
		1234
		Johny
		music
	My algorithm will return:
		1234
		Johny "B" Goode
		music

Relevant properties:
About: Click here to see information about me.
Error: Object type Boolean. Read only. True when SourceString has length of 0.
FieldList: Object type TStringList. Read only. This is where the seperated fields
           come as soon as you put a string into SourceString.
SourceString: Object type String. Put your comma delimited string here.
}

Unit unit_CSVStringInfo;
{$D-,L-,Y-}
interface

uses
  windows,
  sysutils,
  classes,
  dialogs;

type
  TCSVStringInfo = class(TComponent)
  private
    { Private Declarations }
    FFieldList: TStringList;
    FError: Boolean;
    FSourceString: String;
    procedure SetFieldList(sl: TStringList);
    procedure SetSourceString(const s: String);
    procedure SetError(b: Boolean);
  protected
    { Protected Declarations }
  public
    { Public Declarations }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
//  published
    property FieldList: TStringList read FFieldList write SetFieldList;
    property Error: Boolean read FError write SetError default True;
    property SourceString: String read FSourceString write SetSourceString;
  end;

implementation
{--------------------------------------}
{ CSVStringInfo.SetSourceString        }
{--------------------------------------}
procedure TCSVStringInfo.SetSourceString(const s: string);
var
  lenS,
  FldLen,
  i,x: Integer;
  tmpS: String;
  EOFChar: String[1];
begin
  FSourceString := s;
  FFieldList.Clear;
  lenS := Length(s);
  if lenS > 0 then
  begin
    i := 1;
    while (i <= lenS) do
    begin
      if Copy(s,i,1) = '"' then
      begin
        EOFChar := '"';
        i := i + 1;
      end else
        EOFChar := ',';
      tmpS := Copy(s,i,MaxInt);
      FldLen := Length(tmpS);
      for x := 1 to FldLen do  { Seek end of field }
      begin
        if (EOFChar='"') and ((Copy(tmpS,x,2)='",') or
            ((x=FldLen) and (Copy(tmpS,x,1)='"'))) then
        begin
          FldLen := x - 1;
          break;
        end;
        if (EOFChar=',') and (Copy(tmpS,x,1)=',') then
        begin
          FldLen := x - 1;
          break;
        end;
      end;
      FFieldList.Add(Copy(s,i,FldLen));
      { Set i to start position of next field (including it's delimiters)}
      i := i + FldLen + 1;
      if ((EOFChar = '"') and (Copy(s,i,1) = ',')) then
        i := i + 1;
    end;
    FError := False;
  end else
    FError := True;    { Error because string length = 0 }
end;

{--------------------------------------}
{ CSVStringInfo.SetFieldList           }
{--------------------------------------}
procedure TCSVStringInfo.SetFieldList(sl: TStringList);
begin
end;

{--------------------------------------}
{ CSVStringInfo.SetError               }
{--------------------------------------}
procedure TCSVStringInfo.SetError(b: Boolean);
begin
end;

{--------------------------------------}
{ Constructor                          }
{--------------------------------------}
constructor TCSVStringInfo.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FFieldList := TStringList.Create;
  FError := True;
end;

{--------------------------------------}
{ Destructor                           }
{--------------------------------------}
destructor TCSVStringInfo.Destroy;
begin
  FFieldList.Free;
  inherited Destroy;
end;

end.
